﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KZ400B.Data;
using System.Threading;

namespace KZ400B
{
    public class AxlePositionState:PropertyChangedBase
    {
        public AxlePositionState(string axleName,double position)
        {
            m_AxleName = axleName;
            //m_RawPosition = position;
            m_Position = position;
            m_TmpPosition = 0;
            
            m_QueueResult = false;
        }


        private string m_AxleName;

        public string AxleName
        {
            get { return m_AxleName; }
            internal set { m_AxleName = value; }
        }
        private double m_Position;

        public double Position
        {
            get { return m_Position; }
            set
            {
                if (m_Position != value)
                {
                    m_Position = value;
                    this.NotifyPropertyChanged(p => p.Position);
                }
            }
        }

        private double m_TmpPosition;

        public double TmpPosition
        {
            get { return m_TmpPosition; }
            set { m_TmpPosition = value; }
        }

        //private double m_RawPosition;

        //public double RawPosition
        //{
        //    get { return m_RawPosition; }
        //    set { 
        //        m_RawPosition = value; 
            
        //    }
        //}

        //private RunningUnits m_RunUnit;

        //public RunningUnits RunUnit
        //{
        //    get { return m_RunUnit; }
        //    set { m_RunUnit = value; }
        //}


        private bool m_QueueResult;

        public bool QueueResult
        {
            get { return m_QueueResult; }
            set { m_QueueResult = value; }
        }

        private static double computePosition(double rawPosition,double oneStepOffset, RunningUnits unit)
        {
            double pos = rawPosition;
            if (unit != RunningUnits.Step)
            {
                pos = rawPosition * oneStepOffset;
            }
            return pos;
        }

    }
    public delegate void AxlePositionChange(string axleName, Axle axle, double postion,bool ack);
    public class PositionCacheManager
    {
        public AxlePositionState this[string aName]
        {
            get
            {
                if (!string.IsNullOrEmpty(aName))
                {
                    if (AxleStates.ContainsKey(aName))
                    {
                        return AxleStates[aName];
                    }
                }
                return null;
            }
        }
        //public static event AxlePositionChange OnAxlePostionChange;
        private static ObservableDictionary<string, AxlePositionState> s_pmList
            = new ObservableDictionary<string, AxlePositionState>();

        public static ObservableDictionary<string, AxlePositionState> AxleStates
        {
            get { return PositionCacheManager.s_pmList; }
            //set { PositionCacheManager.s_pmList = value; }
        }
        private static object s_psLocker = new object();

        public static bool ChangePosition(string axleName
            , double newPosition)
        {
            return ChangePosition(axleName, newPosition,false);
        }

        public static bool ChangePosition(string axleName
            ,double newPosition 
            ,bool submit
            )
        {

            lock (s_psLocker)
            {
                if (AxleStates.ContainsKey(axleName))
                {

                    if (submit)
                    {
                        AxleStates[axleName].Position = newPosition;
                        AxleStates[axleName].TmpPosition = newPosition;
                        AxleStates[axleName].QueueResult = submit;
                    }
                    else
                    {
                        AxleStates[axleName].TmpPosition = newPosition;
                        AxleStates[axleName].QueueResult = submit;
                    }
                    
                }
                else
                {
                    AxlePositionState aps = new AxlePositionState(axleName,newPosition);
                    aps.QueueResult = submit;
                    AxleStates.Add(axleName, aps);
                }
            }
            return true;
        }

        public static void SubmitChange(string axleName,bool sucess)
        {
            //bool isNotify = false;
            double pos = 0.0F;
            lock (s_psLocker)
            {
                if (AxleStates.ContainsKey(axleName))
                {
                    if (sucess)
                    {
                        AxleStates[axleName].Position = AxleStates[axleName].TmpPosition;
                        pos = AxleStates[axleName].Position;
                    }
                    AxleStates[axleName].QueueResult = sucess;
                    //isNotify = true;
                }
            }
            //if (isNotify)
            //{
            //    if (OnAxlePostionChange != null)
            //    {
            //        OnAxlePostionChange(axleName, AxleCacheManager.getAxle(axleName), pos ,sucess);
            //    }
            //}
        }

        static bool sm_run = false;
        static object sm_lock = new object();

        public static bool IsSimulatoring
        {
            get { lock (sm_lock) { return sm_run; } }
            set { lock (sm_lock) { sm_run = value; } }
        }
        static Random rd = new Random(DateTime.Now.Millisecond);
        static void doSM()
        {
            double counter = 0.0F;
            bool isSet = false;
            while (IsSimulatoring)
            {
                //double newP = DateTime.Now.Ticks;
                double newP = ++counter * 1000;
                foreach (KeyValuePair<string, AxlePositionState> p in AxleStates)
                {
                    
                    p.Value.Position = newP;//rd.NextDouble() * 1000;
                    //Update(p.Key, p.Value);
                    Axle t_Axle = AxleCacheManager.getAxle(p.Key);
                    t_Axle.Position = newP;
                    double dpos = t_Axle.DisplayPosition;
                    ChangePosition(p.Key, dpos, true);
                    AxleCacheManager.Update(t_Axle);
                    AxleStateBarMsg.Instance.AxleState = 
                        string.Format("[{0}] New Position [{1}]"
                            ,p.Key,dpos.ToString(MySetting.PositionDisDeciFormatter)
                            );
                    AxleCacheManager.AxleList[p.Key].AxleActionStatus.VZeroIsSeted = !isSet;
                    //break;
                    Thread.Sleep(500);
                }
                isSet = !isSet;
                //break;
                Thread.Sleep(2000);
                
            }
        }

        public static void SimulatorModify()
        {
            IsSimulatoring = true;
            Thread t_m = new Thread(new ThreadStart(doSM));
            t_m.Start();
        }

        public static void SimulatorStop()
        {
            IsSimulatoring = false;
        }
    }
}
